/*
 * 版权声明 (c) 2025 XXX科技有限公司
 *
 * 本软件及其相关文档文件受版权保护。未经版权所有者明确书面许可，任何单位或个人不得
 * 以任何形式复制、传播、修改、出售、出租、反向工程、反编译或利用本软件的任何部分。
 *
 * 对于任何违反本声明的行为，版权所有者保留追究法律责任的权利。
 */
#ifndef __CONTEXT_H__
#define __CONTEXT_H__
// 标准库
#include <atomic>
#include <memory>
#include <mutex>
#include <map>
#include <unordered_map>

// 第三方库
#include "log.h"

// 工具&通用库
#include "utils/header_global.h"
#include "utils/event.h"

// 基础头文件
#include "model.h"
#include "config.h"
#include "module.h"

// 业务头文件
#include "utils/address.h"
#include "sockness.h"
#include "nat.h"
#include "service.h"
#include "session.h"

using namespace std;

class Module;
class Configure;

class Context {
private:
	// SOCK管理
	unordered_map<int, unique_ptr<Listener>> sock2listener; // socket-port双向映射集合(用于select集中监听等)
	unordered_map<uint16_t, Listener *>      port2listener; // port-socket双向映射集合(用于select集中监听等)
	mutex                                    _spps_lock;    // SP/PS并发安全锁

	// 状态管理
	unordered_map<string, ServiceInfo> LocalService;      // 本地服务表
	unordered_map<uint16_t, NatMate>   StaticServiceList; // 静态服务表
	unordered_map<int, NatMate>        NatPort2Service;   // [NAT地址转换] FD -> 服务
	unordered_map<string, int>         NatService2Port;   // [NAT地址转换] 服务 -> FD

	unordered_map<string, Session> SessionWithNat; // 请求会话,根据Nat五元组适配会已建立的会话信息
	unordered_map<int, Session>    SessionWithFD;  // 响应会话，格局Server的SocketFD查询会话信息

	mutex         _modulesLock;           // 模块安全锁
	mutex         _staticServiceListLock; // 并发安全锁
	mutable mutex _gatewayTableLock;      // 并发安全锁
	mutex         _routerThreadsLock;     // 并发安全锁
	mutex         _localServiceLock;      // 并发安全锁
	mutex         _nat_p2s_lock;          // 并发安全锁
	mutex         _nat_s2p_lock;          // 并发安全锁
	mutex         _sessionnat_lock;       // 并发安全锁
	mutex         _sessionfd_lock;        // 并发安全锁

public:
	Configure                           &config;
	std::vector<std::unique_ptr<Module>> modules;
	unordered_map<string, long long>     GatewayTable;
	explicit inline Context(Configure &config) : config(config) {}
	EventBus eventBus;

	// ---------------------------------------  状态管理 ---------------------------------------

	inline void SetNatP2SMapper(const int port, const NatMate &val) {
		lock_guard<mutex> lock(_nat_p2s_lock); // 主动管理锁
		NatPort2Service[port] = val;
	}
	inline bool GetNatP2SMapper(const int port, NatMate &val) {
		lock_guard<mutex> lock(_nat_p2s_lock);
		auto              it = NatPort2Service.find(port);
		if (it != NatPort2Service.end()) {
			val = it->second;
			return true;
		}
		return false;
	}

	inline unordered_map<int, NatMate> GetNatService() {
		lock_guard<mutex> lock(_nat_p2s_lock);
		return NatPort2Service;
	}

	inline void SetNatS2PMapper(const string &key, const int port) {
		lock_guard<mutex> lock(_nat_s2p_lock);
		NatService2Port[key] = port;
	}

	inline bool GetNatS2PMapper(const string &key, int &port) {
		lock_guard<mutex> lock(_nat_s2p_lock);
		auto              it = NatService2Port.find(key);
		if (it != NatService2Port.end()) {
			port = it->second;
			return true;
		}
		return false;
	}

	inline void SetSessionBytNat(const string &key, const Session value) {
		lock_guard<mutex> lock(_sessionnat_lock);
		SessionWithNat[key] = value;
	}

	inline bool GetSessionBytNat(const string &key, Session &value) {
		lock_guard<mutex> lock(_sessionnat_lock);
		auto              it = SessionWithNat.find(key);
		if (it != SessionWithNat.end()) {
			value = it->second;
			return true;
		}
		return false;
	}

	inline void SetSessionBytFd(const int &key, const Session value) {
		lock_guard<mutex> lock(_sessionfd_lock);
		SessionWithFD[key] = value;
	}

	inline bool GetSessionByFd(const int &key, Session &value) {
		lock_guard<mutex> lock(_sessionfd_lock);
		auto              it = SessionWithFD.find(key);
		if (it != SessionWithFD.end()) {
			value = it->second;
			return true;
		}
		return false;
	}

	inline void SetStaticServiceList(const uint16_t port, const NatMate &val) {
		lock_guard<mutex> lock(_staticServiceListLock); // 主动管理锁
		StaticServiceList[port] = val;
	}

	inline bool GetStaticServiceList(const uint16_t port, NatMate &val) {
		lock_guard<mutex> lock(_staticServiceListLock);
		auto              it = StaticServiceList.find(port);
		if (it != StaticServiceList.end()) {
			val = it->second;
			return true;
		}
		return false;
	}

	inline void SetGatewayTable(const string &ipPort) {
		long long         tm = timestamp_mills();
		lock_guard<mutex> lock(_gatewayTableLock); // 主动管理锁
		GatewayTable[ipPort] = tm;
	}

	inline bool GetGatewayTable(const string ipPort, string &val) const {
		lock_guard<mutex> lock(_gatewayTableLock);
		auto              it = GatewayTable.find(ipPort);
		if (it != GatewayTable.end()) {
			val = it->second;
			return true;
		}
		return false;
	}

	inline bool GatewayTableContains(const string ipPort) const {
		lock_guard<mutex> lock(_gatewayTableLock);
		return GatewayTable.find(ipPort) != GatewayTable.end();
	}

	// FIXME: 「Feature」双缓存技术
	// GatewayTable副本，用于线程安全的遍历
	inline unordered_map<string, long long> GatewayCopyer() const {
		unordered_map<string, long long> copy;
		{
			lock_guard<mutex> lock(_gatewayTableLock);
			copy = GatewayTable; // 深拷贝
		}
		return copy;
	}

	inline void SetLocalService(string serviceName, const ServiceInfo &val) {
		lock_guard<mutex> lock(_localServiceLock); // 主动管理锁
		LocalService[serviceName] = val;
	}

	inline bool GetLocalService(string serviceName, ServiceInfo &val) {
		lock_guard<mutex> lock(_localServiceLock);
		auto              it = LocalService.find(serviceName);
		if (it != LocalService.end()) {
			val = it->second;
			return true;
		}
		return false;
	}
	// 副本，用于线程安全的遍历

	inline unordered_map<string, ServiceInfo> LocalServiceCopyer() const {
		unordered_map<string, ServiceInfo> copy;
		{
			lock_guard<mutex> lock(_gatewayTableLock);
			copy = LocalService; // 深拷贝
		}
		return copy;
	}
	// ---------------------------------------  SOCK管理 ---------------------------------------

	inline void addListener(unique_ptr<Listener> listener) {
		lock_guard<mutex> lock(_spps_lock);
		auto              ptr = listener.get();
		sock2listener.emplace(ptr->sockfd, move(listener));
		port2listener.emplace(ptr->port, ptr);
		log_info("[Listener] %s socket[FD:%d] is running on %d ...", ptr->name, ptr->sockfd, ptr->port);
	}

	inline Listener *getListenerByFD(int fd) {
		lock_guard<mutex> lock(_spps_lock);
		auto              it = sock2listener.find(fd);
		return it != sock2listener.end() ? it->second.get() : nullptr;
	}

	inline Listener *getListenerByPort(uint16_t port) {
		lock_guard<mutex> lock(_spps_lock);
		auto              it = port2listener.find(port);
		return it != port2listener.end() ? it->second : nullptr;
	}

	inline void removeByPort(uint16_t port) {
		lock_guard<mutex> lock(_spps_lock);
		auto              port_it = port2listener.find(port);
		if (port_it != port2listener.end()) {
			auto *listener = port_it->second;
			log_info("[Listener] %s socket[FD:%d] removed.", listener->name, listener->sockfd);
			sock2listener.erase(listener->sockfd);
			port2listener.erase(listener->port);
		}
	}

	inline void removeByFd(int &fd) {
		lock_guard<mutex> lock(_spps_lock);
		auto              fd_it = sock2listener.find(fd);
		if (fd_it != sock2listener.end()) {
			auto *listener = fd_it->second.get();
			log_info("[Listener] %s socket[FD:%d] removed.", listener->name, listener->sockfd);
			sock2listener.erase(listener->sockfd);
			port2listener.erase(listener->port);
		}
		fd = -2; // 主动关闭
	}

	inline vector<int> getAllSockets() {
		lock_guard<mutex> lock(_spps_lock);
		vector<int>       sockets;
		for (const auto &pair: sock2listener) {
			sockets.push_back(pair.first);
		}
		return sockets;
	}

	~Context() {};
};
#endif // NATMATE_CONTEXT_H
